package com.enzoism.testspring.transaction.tx;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

import java.lang.reflect.Method;

public class MyTransactionInterceptor implements MethodInterceptor {

    final ThreadLocal<TransactionInfo> transactionThread = new ThreadLocal<TransactionInfo>();

    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {


        Class targetClass = (methodInvocation.getThis() != null) ? methodInvocation.getThis().getClass() : null;
        //
        if (methodInvocation.getMethod().getName().equals("toString")) {
            return "";
        }

        //begin Transaction
        TransactionInfo txInfo = createTransactionIfNecessary(methodInvocation.getMethod(), methodInvocation);
        Object retVal = null;
        try {
            retVal = methodInvocation.proceed();
        } catch (Throwable e) {
            //回滚相关事务  父类或子类实现
            doCloseTransactionAfterThrowing(geTransactionInfo(), e);
            throw e;
        } finally {
            //设置transaction 状态
            TransactionInfo info = geTransactionInfo();
            info.setSuccessStatus(StatusType.SUCCESS);
            doFinally(info);
        }
        //commit
        doCommitTransactionAfterReturning(geTransactionInfo());
        return retVal;
    }


    private void doFinally(TransactionInfo transactionInfo) {
        setTransactionInfo(transactionInfo);
    }

    private void doCommitTransactionAfterReturning(TransactionInfo geTransactionInfo) {
        System.out.println("------------>>docommit");
    }

    private void doCloseTransactionAfterThrowing(TransactionInfo geTransactionInfo,
                                                 Throwable e) {
        System.out.println("------------>>rollback transaction");

    }

    private TransactionInfo createTransactionIfNecessary(Method method,
                                                         MethodInvocation methodInvocation) {
        System.out.println("------------>>begin transation");
        TransactionInfo transactionInfo = new TransactionInfo();
        setTransactionInfo(transactionInfo);
        return transactionInfo;
    }

    public TransactionInfo geTransactionInfo() {
        return transactionThread.get();
    }

    public void setTransactionInfo(TransactionInfo transactionInfo) {
        transactionThread.set(transactionInfo);
    }
}